package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.mapper.CartInfoMapper;
import com.atguigu.gmall.cart.service.CartInfoService;
import com.atguigu.gmall.common.constant.CartConstants;
import com.atguigu.gmall.common.execption.GmallException;
import com.atguigu.gmall.common.util.GmallThreadLocalUtils;
import com.atguigu.gmall.feign.ProductFeignClient;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.util.concurrent.AtomicDouble;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/***
 * 购物车的业务层接口的实现类
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CartInfoServiceImpl implements CartInfoService {

    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private CartInfoMapper cartInfoMapper;

    /**
     * 新增购物车
     *
     * @param skuId
     * @param num
     */
    @Override
    public void save(Long skuId, Integer num) {
        //从本地线程中获取用户名
        String username = GmallThreadLocalUtils.get();

        //1 根据skuId查询商品信息，远程调用
        SkuInfo skuInfo = productFeignClient.getSkuInfoBySkuId(skuId);
        if (skuInfo == null) {
            return;
        }

        //新增之前判断用户是否重复添加商品
        CartInfo cartInfo = cartInfoMapper.selectOne(new LambdaQueryWrapper<CartInfo>()
                .eq(CartInfo::getUserId, username)
                .eq(CartInfo::getSkuId, skuId));
        if (cartInfo != null) {
            //有记录，只需修改商品的数量
            //获取商品数量
            Integer skuNum = cartInfo.getSkuNum();
            cartInfo.setSkuNum(skuNum + num);
            //修改之前如果数量小于等于0，则删除
            if (cartInfo.getSkuNum() <= 0) {
                cartInfoMapper.deleteById(cartInfo.getId());
            }
            //修改
            cartInfoMapper.updateById(cartInfo);
            return;
        }

        //新增之前判断判断商品数量是否合法
        if (num <= 0) {
            return;
        }

        //2 封装购物车信息对象
        cartInfo = new CartInfo();
        cartInfo.setUserId(username);
        cartInfo.setSkuId(skuId);
        //实时查询价格
        BigDecimal price = productFeignClient.getSkuInfoPriceBySkuId(skuId);
        cartInfo.setCartPrice(price);
        cartInfo.setSkuNum(num);
        cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
        cartInfo.setSkuName(skuInfo.getSkuName());

        //3 新增操作
        cartInfoMapper.insert(cartInfo);
    }

    /**
     * 查询购物车列表
     *
     * @return
     */
    @Override
    public List<CartInfo> listCartInfoByUsername() {
        //从本地线程中获取用户名
        String username = GmallThreadLocalUtils.get();

        //1 查询
        List<CartInfo> cartInfoList = cartInfoMapper.selectList(new LambdaQueryWrapper<CartInfo>().eq(CartInfo::getUserId, username));

        //2 返回
        return cartInfoList;
    }

    /**
     * 删除购物车商品
     *
     * @param skuId
     */
    @Override
    public void removeByUsernameAndSkuId(Long skuId) {
        //从本地线程中获取用户名
        String username = GmallThreadLocalUtils.get();

        //1 删除操作，注意：每个用户只能删除自己购物车中的内容
        int delete = cartInfoMapper.delete(new LambdaQueryWrapper<CartInfo>()
                .eq(CartInfo::getUserId, username)
                .eq(CartInfo::getSkuId, skuId));

        if (delete < 0) {
            throw new GmallException("删除操作失败", null);
        }
    }

    /**
     * 勾选操作
     *
     * @param id
     * @param status
     */
    @Override
    public void checkOrUncheck(Long id, Short status) {
        //从本地线程中获取用户名
        String username = GmallThreadLocalUtils.get();

        int i = 0;
        //1 判断是否为单条商品勾选，还是全选
        if (id == null) {
            //为全选
            i = cartInfoMapper.checkAll(username, status);
        } else {
            //勾选单个
            i = cartInfoMapper.checkOne(username, id, status);
        }

        //判断是否操作成功
        if (i < 0) {
            throw new GmallException("修改选中操作失败", null);
        }
    }

    /**
     * 用户登录时合并购物车
     *
     * @param cartInfoList
     */
    @Override
    public void mergeCart(List<CartInfo> cartInfoList) {
        //遍历
        cartInfoList.stream().forEach(cartInfo -> {
            //直接调用新增的方法
            this.save(cartInfo.getSkuId(), cartInfo.getSkuNum());
        });
    }

    /**
     * 下单使用统计最新的购物车信息
     *
     * @return
     */
    @Override
    public Map MapOrderCartMap() {
        //初始化map
        Map<String, Object> map = new HashMap();

        //查询数据库中的被选中的商品
        List<CartInfo> cartInfoList =
                cartInfoMapper.selectList(
                        new LambdaQueryWrapper<CartInfo>()
                                .eq(CartInfo::getUserId, GmallThreadLocalUtils.get())
                                .eq(CartInfo::getIsChecked, CartConstants.CART_CHECK));
        if (cartInfoList.isEmpty() || cartInfoList.size() < 0) {
            return null;
        }

        //初始化商品总数量
        AtomicInteger num = new AtomicInteger();
        //初始化商品总金额
        AtomicDouble amount = new AtomicDouble();

        //遍历选中的商品
        List<CartInfo> cartInfoListNew = cartInfoList.stream().map(cartInfo -> {
            //累加商品数量
            num.getAndAdd(cartInfo.getSkuNum());

            //获取到商品的最新价格
            BigDecimal price = productFeignClient.getSkuInfoPriceBySkuId(cartInfo.getSkuId());
            cartInfo.setSkuPrice(price);
            //累加商品金额 （价格 x 数量）
            amount.getAndAdd(price.multiply(new BigDecimal(cartInfo.getSkuNum().toString())).doubleValue());

            return cartInfo;
        }).collect(Collectors.toList());

        //封装map
        map.put("cartInfoList", cartInfoListNew);
        map.put("num", num);
        map.put("amount", amount);

        return map;
    }

    /**
     * 用户下单成功，清空购物车
     *
     * @return
     */
    @Override
    public Boolean clearCart() {
        int delete = cartInfoMapper.delete(
                new LambdaQueryWrapper<CartInfo>()
                        .eq(CartInfo::getUserId, GmallThreadLocalUtils.get())
                        .eq(CartInfo::getIsChecked, CartConstants.CART_CHECK));
        return delete > 0;
    }
}
